using System;
using System.Collections.Generic;
using UnityEngine;
using Utils.Singleton;

namespace Utils.Events
{
    public class EventCenter : MonoSingleton<EventCenter>
    {
        // 使用Dictionary存储不同类型的SimpleEvent，key为事件数据类型
        private readonly Dictionary<Type, ISimpleEvent> _eventDic = new Dictionary<Type, ISimpleEvent>();

        #region 事件注册、注销和触发方法

        /// <summary>
        /// 注册事件
        /// </summary>
        /// <typeparam name="T">事件数据类型（允许类和结构体，要求有无参数构造函数）</typeparam>
        /// <param name="action">事件处理函数</param>
        /// <returns>可用于注销的IEventUnregister接口</returns>
        public IEventUnregister Register<T>(Action<T> action)
        {
            if (action == null)
            {
                throw new ArgumentNullException(nameof(action));
            }

            Type eventType = typeof(T);

            // 如果字典中不存在该类型的事件，则创建一个新的SimpleEvent<T>
            if (!_eventDic.ContainsKey(eventType))
            {
                _eventDic[eventType] = new SimpleEvent<T>();
            }

            // 获取该类型的SimpleEvent<T>并注册事件处理函数
            SimpleEvent<T> simpleEvent = (SimpleEvent<T>)_eventDic[eventType];
            return simpleEvent.Register(action);
        }

        /// <summary>
        /// 注销事件
        /// </summary>
        /// <typeparam name="T">事件数据类型（允许类和结构体，要求有无参数构造函数）</typeparam>
        /// <param name="action">要注销的事件处理函数</param>
        public void Unregister<T>(Action<T> action)
        {
            if (action == null)
            {
                return;
            }

            Type eventType = typeof(T);

            // 如果字典中存在该类型的事件，则注销事件处理函数
            if (_eventDic.TryGetValue(eventType, out var value))
            {
                SimpleEvent<T> simpleEvent = (SimpleEvent<T>)value;
                simpleEvent.Unregister(action);
            }
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <typeparam name="T">事件数据类型（允许类和结构体，要求有无参数构造函数）</typeparam>
        /// <param name="data">事件数据</param>
        public void Invoke<T>(T data)
        {
            Type eventType = typeof(T);

            // 如果字典中存在该类型的事件，则触发事件
            if (_eventDic.TryGetValue(eventType, out var value))
            {
                SimpleEvent<T> simpleEvent = (SimpleEvent<T>)value;
                simpleEvent.Invoke(data);
            }
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 清除所有事件
        /// </summary>
        public void ClearAllEvents()
        {
            _eventDic.Clear();
        }

        /// <summary>
        /// 清除指定类型的事件
        /// </summary>
        /// <typeparam name="T">事件数据类型（允许类和结构体，要求有无参数构造函数）</typeparam>
        public void ClearEvent<T>()
        {
            Type eventType = typeof(T);

            if (_eventDic.ContainsKey(eventType))
            {
                _eventDic.Remove(eventType);
            }
        }

        /// <summary>
        /// 获取指定类型的事件监听器数量
        /// </summary>
        /// <typeparam name="T">事件数据类型（允许类和结构体，要求有无参数构造函数）</typeparam>
        /// <returns>监听器数量</returns>
        public int GetListenerCount<T>()
        {
            Type eventType = typeof(T);

            if (_eventDic.ContainsKey(eventType))
            {
                SimpleEvent<T> simpleEvent = _eventDic[eventType] as SimpleEvent<T>;
                if (simpleEvent != null)
                {
                    return simpleEvent.Count;
                }
                else
                {
                    Debug.LogError($"Failed to cast event of type {eventType.Name} to SimpleEvent<{typeof(T).Name}> when getting listener count");
                }
            }

            return 0;
        }

        #endregion

        protected override bool NotDestroyed => true;
    }
}